package de.tabiteuea.gui.dialogs;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;

import de.tabiteuea.gui.utils.ITabiXMLConstants;

/**
 * Dialog for opening a file and reading its content.
 * 
 * @author Sebastian Lippert
 * 
 */

public class OpenFileDialog {

	private FileDialog dlg;
	private String path;
	private StringBuffer corpus;
	boolean isInterrupted = true;

	/**
	 * Constructor
	 * 
	 * @param parent
	 *            Parent composite
	 * @param dialogMessage
	 *            Title message of the dialog
	 * @param fileExtension
	 *            Valid file formats
	 * @throws IOException
	 *             Will be thrown when something went definitely wrong
	 * @throws XMLStreamException
	 *             Will be thrown when something went wrong on the XML parsing
	 */

	public OpenFileDialog(Composite parent, String dialogMessage,
			String[] fileExtension) throws IOException, XMLStreamException {

		corpus = new StringBuffer();

		// call common file dialog with given parameters
		dlg = new FileDialog(parent.getShell());
		dlg.setText(dialogMessage);
		dlg.setFilterExtensions(fileExtension);
		dlg.setFilterPath(System.getProperty("user.home")); //$NON-NLS-1$

		path = dlg.open();

		// parse file in raw mode (nothing will be changed except the leading
		// newLine) and save content in a StringBuffer
		if (path != null) {

			// special parsing for XML files
			if (path.endsWith(".xml")) {
				parseXML(path);
			} else {

				BufferedReader myBuffer = new BufferedReader(new FileReader(
						path));
				String line = null;

				/*
				 * reading the input line by line
				 * 
				 * NOTE: After the last line a newline will be appended. Its
				 * cheaper to handle this later than to remove the last
				 * newLine
				 */
				while ((line = myBuffer.readLine()) != null) {

					corpus.append(line);
					corpus.append(System.getProperty("line.separator"));

				}

				myBuffer.close();
			}
			isInterrupted = false;
		}
	}

	/*
	 * Method is specialized to parse XML files. By convention only the
	 * characters within <text> tags should be read. So we search this tag an
	 * append the following text to our buffer.
	 */

	private void parseXML(String path) throws FileNotFoundException,
			XMLStreamException {

		corpus = new StringBuffer();
		String encoding = null;

		// try to read encoding of the XML file
		XMLInputFactory factory = XMLInputFactory.newInstance();
		XMLStreamReader reader = factory
				.createXMLStreamReader(new FileInputStream(path));
		encoding = reader.getCharacterEncodingScheme();

		// use encoding if it was detected, otherwise the system default
		// encoding will be used
		if (encoding != null)
			reader = factory.createXMLStreamReader(new FileInputStream(path),
					encoding);

		// read file
		while (reader.hasNext()) {
			int event = reader.next();

			switch (event) {
			case XMLStreamConstants.END_DOCUMENT:
				reader.close();
				break;
			case XMLStreamConstants.START_ELEMENT:

				// find the <text> element
				if (reader.getLocalName().equals(ITabiXMLConstants.TEXT_TAG)) {

					// next element should be our input
					reader.next();
					if (!reader.isWhiteSpace())
						corpus.append(reader.getText());

				}
				break;

			}
		}

	}

	/**
	 * Indicates whether the cancel button was pushed or not
	 * 
	 * @return Boolean result
	 */

	public boolean isInterrupted() {
		return isInterrupted;
	}

	/**
	 * Getter for absolute path to the selected file
	 * 
	 * @return Absolute path
	 */

	public String getPath() {

		if (path == null)
			return new String();

		return path;
	}

	/**
	 * Getter for parsed content of the selected file
	 * 
	 * @return Content
	 */

	public String getCorpus() {

		if (corpus == null)
			return new String();

		return corpus.toString();
	}

	/**
	 * Getter for file name of the selected file
	 * 
	 * @return File name
	 */

	public String getFileName() {

		if (dlg.getFileName() == null)
			return new String();

		return dlg.getFileName();
	}

}
